package cn.zhentao.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;

/**
 * 图片质量检查工具类
 * 
 * 用于检查图片的基本质量指标，确保图片适合人脸识别处理
 * 包括尺寸检查、格式验证、文件大小检查等
 * 
 * @author 田国刚
 * @since 2023-04-16
 */
@Slf4j
@Component
public class ImageQualityChecker {

    /**
     * 最小图片宽度（像素）
     */
    private static final int MIN_WIDTH = 100;
    
    /**
     * 最小图片高度（像素）
     */
    private static final int MIN_HEIGHT = 100;
    
    /**
     * 推荐最小图片宽度（像素）
     */
    private static final int RECOMMENDED_MIN_WIDTH = 300;
    
    /**
     * 推荐最小图片高度（像素）
     */
    private static final int RECOMMENDED_MIN_HEIGHT = 300;
    
    /**
     * 最大文件大小（字节）- 5MB
     */
    private static final long MAX_FILE_SIZE = 5 * 1024 * 1024;

    /**
     * 检查字节数组图片质量
     * 
     * @param imageBytes 图片字节数组
     * @return ImageQualityResult 质量检查结果
     */
    public ImageQualityResult checkImageQuality(byte[] imageBytes) {
        ImageQualityResult result = new ImageQualityResult();
        
        try {
            // 1. 检查文件大小
            if (imageBytes.length > MAX_FILE_SIZE) {
                result.addWarning("图片文件过大: " + (imageBytes.length / 1024 / 1024) + "MB，建议小于5MB");
            }
            
            if (imageBytes.length < 1024) {
                result.addError("图片文件过小: " + imageBytes.length + "字节，可能不是有效图片");
                return result;
            }
            
            // 2. 尝试读取图片
            BufferedImage image;
            try (ByteArrayInputStream bis = new ByteArrayInputStream(imageBytes)) {
                image = ImageIO.read(bis);
            }
            
            if (image == null) {
                result.addError("无法读取图片，可能是不支持的格式或损坏的文件");
                return result;
            }
            
            // 3. 检查图片尺寸
            int width = image.getWidth();
            int height = image.getHeight();
            
            log.info("图片尺寸: {}x{}", width, height);
            
            if (width < MIN_WIDTH || height < MIN_HEIGHT) {
                result.addError(String.format("图片尺寸过小: %dx%d，最小要求: %dx%d", 
                    width, height, MIN_WIDTH, MIN_HEIGHT));
            } else if (width < RECOMMENDED_MIN_WIDTH || height < RECOMMENDED_MIN_HEIGHT) {
                result.addWarning(String.format("图片尺寸较小: %dx%d，推荐尺寸: %dx%d以上", 
                    width, height, RECOMMENDED_MIN_WIDTH, RECOMMENDED_MIN_HEIGHT));
            }
            
            // 4. 检查宽高比
            double aspectRatio = (double) width / height;
            if (aspectRatio < 0.5 || aspectRatio > 2.0) {
                result.addWarning(String.format("图片宽高比异常: %.2f，建议使用接近正方形的图片", aspectRatio));
            }
            
            // 5. 设置基本信息
            result.setWidth(width);
            result.setHeight(height);
            result.setFileSize(imageBytes.length);
            result.setFormat(getImageFormat(imageBytes));
            
            log.info("图片质量检查完成 - 宽度: {}, 高度: {}, 大小: {}KB, 格式: {}", 
                width, height, imageBytes.length / 1024, result.getFormat());
            
        } catch (IOException e) {
            log.error("图片质量检查时发生IO异常", e);
            result.addError("图片读取失败: " + e.getMessage());
        } catch (Exception e) {
            log.error("图片质量检查时发生未知异常", e);
            result.addError("图片检查失败: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 检查文件图片质量
     * 
     * @param file 图片文件
     * @return ImageQualityResult 质量检查结果
     */
    public ImageQualityResult checkImageQuality(File file) {
        ImageQualityResult result = new ImageQualityResult();
        
        try {
            if (!file.exists()) {
                result.addError("文件不存在: " + file.getAbsolutePath());
                return result;
            }
            
            if (!file.canRead()) {
                result.addError("文件无法读取: " + file.getAbsolutePath());
                return result;
            }
            
            // 读取图片
            BufferedImage image = ImageIO.read(file);
            if (image == null) {
                result.addError("无法读取图片文件，可能是不支持的格式");
                return result;
            }
            
            // 设置基本信息
            result.setWidth(image.getWidth());
            result.setHeight(image.getHeight());
            result.setFileSize(file.length());
            result.setFormat(getImageFormatFromFile(file));
            
            // 检查尺寸
            if (image.getWidth() < MIN_WIDTH || image.getHeight() < MIN_HEIGHT) {
                result.addError(String.format("图片尺寸过小: %dx%d", image.getWidth(), image.getHeight()));
            }
            
        } catch (IOException e) {
            log.error("检查文件图片质量时发生异常", e);
            result.addError("文件读取失败: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 从字节数组判断图片格式
     * 
     * @param imageBytes 图片字节数组
     * @return 图片格式字符串
     */
    private String getImageFormat(byte[] imageBytes) {
        if (imageBytes.length < 4) {
            return "UNKNOWN";
        }
        
        // JPEG格式检查
        if (imageBytes[0] == (byte) 0xFF && imageBytes[1] == (byte) 0xD8) {
            return "JPEG";
        }
        
        // PNG格式检查
        if (imageBytes[0] == (byte) 0x89 && imageBytes[1] == (byte) 0x50 && 
            imageBytes[2] == (byte) 0x4E && imageBytes[3] == (byte) 0x47) {
            return "PNG";
        }
        
        // GIF格式检查
        if (imageBytes[0] == (byte) 0x47 && imageBytes[1] == (byte) 0x49 && imageBytes[2] == (byte) 0x46) {
            return "GIF";
        }
        
        // BMP格式检查
        if (imageBytes[0] == (byte) 0x42 && imageBytes[1] == (byte) 0x4D) {
            return "BMP";
        }
        
        return "UNKNOWN";
    }

    /**
     * 从文件名判断图片格式
     * 
     * @param file 图片文件
     * @return 图片格式字符串
     */
    private String getImageFormatFromFile(File file) {
        String fileName = file.getName().toLowerCase();
        if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
            return "JPEG";
        } else if (fileName.endsWith(".png")) {
            return "PNG";
        } else if (fileName.endsWith(".gif")) {
            return "GIF";
        } else if (fileName.endsWith(".bmp")) {
            return "BMP";
        }
        return "UNKNOWN";
    }

    /**
     * 图片质量检查结果类
     */
    public static class ImageQualityResult {
        private boolean valid = true;
        private java.util.List<String> errors = new java.util.ArrayList<>();
        private java.util.List<String> warnings = new java.util.ArrayList<>();
        private int width;
        private int height;
        private long fileSize;
        private String format;

        public void addError(String error) {
            this.errors.add(error);
            this.valid = false;
        }

        public void addWarning(String warning) {
            this.warnings.add(warning);
        }

        // Getters and Setters
        public boolean isValid() { return valid; }
        public java.util.List<String> getErrors() { return errors; }
        public java.util.List<String> getWarnings() { return warnings; }
        public int getWidth() { return width; }
        public void setWidth(int width) { this.width = width; }
        public int getHeight() { return height; }
        public void setHeight(int height) { this.height = height; }
        public long getFileSize() { return fileSize; }
        public void setFileSize(long fileSize) { this.fileSize = fileSize; }
        public String getFormat() { return format; }
        public void setFormat(String format) { this.format = format; }

        @Override
        public String toString() {
            return String.format("ImageQualityResult{valid=%s, width=%d, height=%d, fileSize=%d, format='%s', errors=%s, warnings=%s}",
                valid, width, height, fileSize, format, errors, warnings);
        }
    }
}
